//
//  GYXRefreshControl.swift
//  RefreshControl
//
//  Created by Twisal on 2017/3/28.
//  Copyright © 2017年 Twisal. All rights reserved.
//

import UIKit


/// 刷新状态切换的临界点
private let refreshOffset: CGFloat = 126

/// 刷新状态
///
/// - Normal: 普通状态,什么都不做
/// - Pulling: 超过临界点, 如果放手, 开始刷新
/// - willRefresh: 用户超过临界点, 并且放手
enum GYXRefreshState {
    case Normal
    case Pulling
    case willRefresh
}

// MARK: - 刷新控件
class GYXRefreshControl: UIControl {

    
    /// 用来记录父视图 UITableView/UICollectionView
    var scrollView : UIScrollView?
    
    /// 懒加载刷新控件
    lazy var refreshView: GYXRefreshView = GYXRefreshView.refreshView()
    /// 重写构造函数- 用于纯代码
    init() {
        super.init(frame: CGRect())
        setupUI()
    }
    /// 用于storyboard
    required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
        setupUI()
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        // 判断父视图是否存在
        guard let sv = newSuperview as? UIScrollView else {
            return
        }
        
        // 记录父视图
        scrollView = sv
        
        // KVO--对父视图的contentOffset进行监听
        scrollView?.addObserver(self, forKeyPath: "contentOffset", options: [], context: nil)
    }
    
    
    /// 移除通知
    override func removeFromSuperview() {
        superview?.removeObserver(self, forKeyPath: "contentOffset")
        super.removeFromSuperview()
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  
        // 判断视图是否存在
        guard let sv = scrollView else {
            return
        }
        
        // 刷新控件的高度
        let height = -(sv.contentInset.top + sv.contentOffset.y)
        
        // 记录刷新视图的高度, 如果正在刷新中, 不传递
        if refreshView.refreshState != .willRefresh {
            
            refreshView.viewHeight = height
        }
        
        // 如果,刷新控件的高度小于0, 刷新控件就没有frame
        if height < 0 {
            return
        }
        // 设置刷新控件的frame
        self.frame = CGRect(x: 0, y: -height, width: sv.bounds.width, height: height)
        
        // 判断当前状态
        if sv.isDragging {
            if height > refreshOffset && refreshView.refreshState == .Normal {
                print("放开刷新")
                refreshView.refreshState = .Pulling
            } else if height <= refreshOffset && refreshView.refreshState == .Pulling {
                print("继续使劲...")
                refreshView.refreshState = .Normal
            }
        } else {
            // 放开
            if refreshView.refreshState == .Pulling {
                print("开始准备刷新")
                beginRefreshing()
                sendActions(for: .valueChanged)
            }
        }

    }
    
    
    /// 开始刷新
    func beginRefreshing() {
        print("开始刷新..")
        // 判断父视图是否存在
        guard let sv = scrollView else {
            return
        }
        
        // 判断当前状态是否是正在刷新
        if refreshView.refreshState == .willRefresh {
            return
        }
        
        // 设置当前状态为正在刷新状态
        refreshView.refreshState = .willRefresh
        // 设置刷新视图的父视图的高度
        refreshView.viewHeight = refreshOffset
        // 重新设置scrollView的视图缩进
        var inset = sv.contentInset
        inset.top += refreshOffset
        sv.contentInset = inset
    }

    /// 结束刷新
    func endRefreshing() {
        print("结束刷新")
        // 判断父视图是否存在
        guard let sv = scrollView else {
            return
        }
        
        // 判断当前状态是否是正在刷新
        if refreshView.refreshState != .willRefresh {
            return
        }
        
        // 设置当前状态为正常状态
        refreshView.refreshState = .Normal
        
        // 重新设置scrollView的视图缩进
        var inset = sv.contentInset
        inset.top -= refreshOffset
        sv.contentInset = inset
    }
}


// MARK: - 初始化视图
extension GYXRefreshControl {
    fileprivate func setupUI() {
        backgroundColor = superview?.backgroundColor
        // 裁剪多余部分
//        clipsToBounds = true
        // 添加子控件
        addSubview(refreshView)
        
        // 关闭autoResizing
        refreshView.translatesAutoresizingMaskIntoConstraints = false
        // 为子控件添加约束
        addConstraint(NSLayoutConstraint(item: refreshView,
                                                     attribute: .centerX,
                                                     relatedBy: .equal,
                                                     toItem: self,
                                                     attribute: .centerX,
                                                     multiplier: 1.0,
                                                     constant: 0.0))
        addConstraint(NSLayoutConstraint(item: refreshView,
                                                     attribute: .bottom,
                                                     relatedBy: .equal,
                                                     toItem: self,
                                                     attribute: .bottom,
                                                     multiplier: 1.0,
                                                     constant: 0.0))
        addConstraint(NSLayoutConstraint(item: refreshView,
                                                     attribute: .width,
                                                     relatedBy: .equal,
                                                     toItem: nil,
                                                     attribute: .notAnAttribute,
                                                     multiplier: 1.0,
                                                     constant: refreshView.bounds.width))
        addConstraint(NSLayoutConstraint(item: refreshView,
                                                     attribute: .height,
                                                     relatedBy: .equal,
                                                     toItem: nil,
                                                     attribute: .notAnAttribute,
                                                     multiplier: 1.0,
                                                     constant: refreshView.bounds.height))
       
        
    }
}
